<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Fabric.js Image Filters</title>
    <script src="https://cdn.jsdelivr.net/npm/fabric"></script>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
    <h1>Fabric.js Image Filters</h1>
    <input type="file" id="imageLoader" name="imageLoader"/>
    <canvas id="canvas"></canvas>
    <div>
        <p>亮度: <input type="range" id="brightness" min="-1" max="1" step="0.1" value="0"></p>
        <p>对比度: <input type="range" id="contrast" min="-1" max="1" step="0.1" value="0"></p>
        <p>饱和度: <input type="range" id="saturation" min="-1" max="1" step="0.1" value="0"></p>
        <p>色调: <input type="range" id="hue" min="-1" max="1" step="0.1" value="0"></p>
        <p>锐化: <input type="range" id="sharpen" min="0" max="1" step="0.1" value="0"></p>
    </div>
    <script>
        const canvas = new fabric.Canvas('canvas');
        let imgObj;

        document.getElementById('imageLoader').addEventListener('change', handleImage, false);

        function handleImage(e) {
            const reader = new FileReader();
            reader.onload = function(event) {
                const imgElement = new Image();
                imgElement.src = event.target.result;
                imgElement.onload = function() {
                    const imgInstance = new fabric.Image(imgElement, {
                        scaleX: canvas.width / imgElement.width,
                        scaleY: canvas.height / imgElement.height
                    });
                    
                    canvas.setWidth(imgElement.width);
                    canvas.setHeight(imgElement.height);

                    imgInstance.filters.push(
                        new fabric.Image.filters.Brightness({brightness: 0}),
                        new fabric.Image.filters.Contrast({contrast: 0}),
                        new fabric.Image.filters.Saturation({saturation: 0}),
                        new fabric.Image.filters.HueRotation({rotation: 0}),
                        new fabric.Image.filters.Convolute({
                            matrix: [0, 0, 0, 0, 1, 0, 0, 0, 0]
                        })
                    );

                    if (imgObj) {
                        canvas.remove(imgObj);
                    }

                    imgInstance.applyFilters();
                    canvas.add(imgInstance);
                    canvas.setActiveObject(imgInstance);
                    imgObj = imgInstance;
                };
            };
            reader.readAsDataURL(e.target.files[0]);
        }

        function updateFilter(index, value) {
            if (imgObj) {
                imgObj.filters[index] = value;
                imgObj.applyFilters();
                canvas.renderAll();
            }
        }

        document.getElementById('brightness').addEventListener('input', function(e) {
            const brightnessFilter = new fabric.Image.filters.Brightness({brightness: parseFloat(e.target.value)});
            updateFilter(0, brightnessFilter);
        });

        document.getElementById('contrast').addEventListener('input', function(e) {
            const contrastFilter = new fabric.Image.filters.Contrast({contrast: parseFloat(e.target.value)});
            updateFilter(1, contrastFilter);
        });

        document.getElementById('saturation').addEventListener('input', function(e) {
            const saturationFilter = new fabric.Image.filters.Saturation({saturation: parseFloat(e.target.value)});
            updateFilter(2, saturationFilter);
        });

        document.getElementById('hue').addEventListener('input', function(e) {
            const hueRotationFilter = new fabric.Image.filters.HueRotation({rotation: parseFloat(e.target.value) * Math.PI});
            updateFilter(3, hueRotationFilter);
        });

        document.getElementById('sharpen').addEventListener('input', function(e) {
            const sharpenValue = parseFloat(e.target.value);
            const sharpenFilter = new fabric.Image.filters.Convolute({
                matrix: [
                    0, -sharpenValue, 0,
                    -sharpenValue, 1 + (4 * sharpenValue), -sharpenValue,
                    0, -sharpenValue, 0
                ]
            });
            updateFilter(4, sharpenFilter);
        });
    </script>
</body>
</html>
